<?php
/**
* Page manager.
*
* Copyright (c) 2009 James Gauld <james@jamesgauld.net>
* This file is part of Scribble.
* @license http://www.scribblecms.co.uk/license.txt
*
* @package Scribble
*/
use Buan\Config;
use Buan\Core;
use Buan\Model;
use Buan\ModelCriteria;
use Buan\SystemLog;
class PageManager extends ScribbleMasterModelManager {

	/**
	* Convert the given string to a valid URL.
	*
	* @param string String to convert
	* @return string
	*/
	static public function convertToUrl($url) {
		return preg_replace("/\-+$/", "", preg_replace("/^\-+/", "", preg_replace("/\-+/", "-", preg_replace("/[^a-z0-9_\.]/", "-", preg_replace("/[']/", "", strtolower($url))))));
	}

	/**
	* Loads a page given a unique permalink string.
	*
	* @param Buan\Model Model to save (must have "permalink" column populated)
	* @return bool
	*/
	public function loadByPermalink($model) {
		$c = new ModelCriteria();
		$c->addClause(ModelCriteria::EQUALS, 'permalink', $model->permalink);
		$models = self::select('Page', $c);
		if(!empty($models)) {
			$model->populateFromArray($models[0]);
			$model->isInDatabase(TRUE);
			$model->hasChanged(FALSE);
			return TRUE;
		}
		return FALSE;
	}

	/**
	* Returns the Page in the specified Site that is represented by the given URL,
	* or NULL if not found.
	*
	* @param SiteModel The site from which to load the page
	* @param string A absolute URL with or without the FQDN
	* @return PageModel|NULL
	*/
	static public function loadByUrlCommand($site, $url) {

		// If the passed site is non-existent then we won't continue looking
		if($site===NULL) {
			return NULL;
		}

		// If given an absolute url, extract only the path
		if(preg_match("/^http:\/\//i", $url)) {
			$url = parse_url($url, PHP_URL_PATH);
		}

		// Remove leading slash
		$url = preg_replace("/^\/+/", "", $url);

		// Strip url suffix if not already done so
		$url = preg_replace("/".preg_quote(Config::get('ext.Scribble.urlSuffix'), "/")."$/", "", $url);

		// Find a matching page
		if($url!='' && $url!='index') {

			// Find absolute match
			$c = new ModelCriteria();
			$c->addClause(ModelCriteria::EQUALS, 'customurl', "/{$url}");
			$c->addClause(ModelCriteria::EQUALS, 'site_id', $site->id);
			$models = self::select('Page', $c);
			$tp = Config::get('ext.Scribble.dbTablePrefix');

			if(!$models->isEmpty()) {
				$page = $models[0];
			}

			// Find relative match
			else {
				$c = new ModelCriteria();
				$c->addClause(ModelCriteria::EQUALS, 'page0.site_id', $site->id);
				$nodes = explode("/", $url);
				foreach($nodes as $k=>$n) {
					$c->selectField("page{$k}.url", "url{$k}");
					$c->selectField("page{$k}.customurl", "customurl{$k}");
					if($k==count($nodes)-1) {
						$c->selectField("page{$k}.id", "pageid");
					}
					if($k==0) {
						$c->selectTable("{$tp}page AS page{$k}");
					}
					else {
						$c->leftJoin("{$tp}page AS page{$k}", "page".($k-1).".id=page{$k}.page_id");
					}
	
					$g = $c->addGroup(ModelCriteria::LOGIC_OR, ModelCriteria::HAVING);
					$g->addClause(ModelCriteria::EQUALS, "url{$k}", $n);
					$g->addClause(ModelCriteria::EQUALS, "customurl{$k}", $n);
					$g->addClause(ModelCriteria::EQUALS, "customurl{$k}", "/{$n}");
				}
				$stmt = self::sqlQuery($c);
				$page = NULL;
				while($rec = $stmt->fetch(PDO::FETCH_OBJ)) {
					$page = Model::create('Page');
					$page->id = $rec->pageid;
					$page->getModelManager()->load($page);
				}
			}
		}
		else {
			$c = new ModelCriteria();
			$c->addClause(ModelCriteria::EQUALS, 'isindex', 1);
			$c->addClause(ModelCriteria::EQUALS, 'site_id', $site->id);
			$pages = self::select('Page', $c);
			$page = $pages->isEmpty() ? NULL : $pages[0];
		}

		// Result
		return $page;
	}

	/**
	* Updates the "datemodified" column and sets the "permalink" for new models.
	* We also ensure that no other Pages are using the same url part in order to
	* avoid conflicts.
	*
	* @param Model Model being saved
	* @return bool
	*/
	public function save($model) {
		if(!$model->isInDatabase() || $model->permalink=='') {
			$model->permalink = uniqid();
		}
		if($model->hasChanged()) {
			$model->dateexpire = (int)$model->dateexpire;
			$model->datepublish = (int)$model->datepublish;
			$model->datemodified = time();
			$tp = Config::get('ext.Scribble.dbTablePrefix');
			if($model->hasCustomRelativeUrl()) {
				$conflicts = self::sqlQuery("SELECT COUNT(*) AS c FROM {$tp}page WHERE id!=? AND (customurl=? OR url=?) AND page_id=? AND site_id=?", array($model->id, $model->customurl, $model->customurl, $model->page_id, $model->site_id))->fetch(PDO::FETCH_OBJ)->c;
			}
			else if($model->hasCustomAbsoluteUrl()) {
				$conflicts = self::sqlQuery("SELECT COUNT(*) AS c FROM {$tp}page WHERE id!=? AND customurl=? AND site_id=?", array($model->id, $model->customurl, $model->site_id))->fetch(PDO::FETCH_OBJ)->c;
			}
			else {
				$conflicts = self::sqlQuery("SELECT COUNT(*) AS c FROM {$tp}page WHERE id!=? AND url=? AND page_id=? AND site_id=?", array($model->id, $model->url, $model->page_id, $model->site_id))->fetch(PDO::FETCH_OBJ)->c;
			}
			if($conflicts>0) {
				SystemLog::add(array('Another page is already using the url "%s"', $model->url), SystemLog::WARNING);
				return FALSE;
			}
		}
		return parent::save($model);
	}
}
?>